package com.feidee.data.report.util.quartz;

import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobBuilder;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.SchedulerFactory;
import org.quartz.TriggerBuilder;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;

public class QuartzUtil {

	private static Logger logger = Logger.getLogger(QuartzUtil.class);
	private static SchedulerFactory schedulerFactory;
	private static Scheduler scheduler = null;

	static {
		try {
			schedulerFactory = new StdSchedulerFactory();
			scheduler = schedulerFactory.getScheduler();
		} catch (SchedulerException e) {
			logger.error("Quartz定时任务SchdulerFactory初始化失败...", e);
		}
	}

	/**
	 * 启动schduler
	 */
	public static void startJobs() {
		try {
			if (!scheduler.isShutdown()) {
				scheduler.start();
			}
		} catch (Exception e) {
			logger.error("Quartz定时任务SchdulerFactory启动失败...", e);
		}
	}

	/**
	 * 停止schduler
	 */
	public static void shutDownJobs() {
		try {
			if (!scheduler.isShutdown()) {
				scheduler.shutdown();
			}
		} catch (Exception e) {
			logger.error("Quartz定时任务SchdulerFactory停止失败...", e);
		}
	}

	/**
	 * 添加定时Job
	 * 
	 * @param job
	 */
	public static void addJob(BaseQuartzJob job) {
		try {
			JobDetail jobDetail = JobBuilder.newJob(job.getClass()).withIdentity(job.getJobName(), job.getGroupName())
					.build();
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getGroupName())
					.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpressStr())).build();

			scheduler.scheduleJob(jobDetail, trigger);
			// 启动scheduler
			startJobs();
		} catch (Exception e) {
			logger.error("Quartz定时任务添加定时任务失败...", e);
		}
	}
	
	/**
	 * 添加定时Job,并设置元数据
	 * 
	 * @param job
	 */
	public static void addJob(BaseQuartzJob job, Map<String, Object> metadataMap) {
		try {
			JobDetail jobDetail = JobBuilder.newJob(job.getClass()).withIdentity(job.getJobName(), job.getGroupName())
					.build();
			JobDataMap jobDataMap = jobDetail.getJobDataMap();
			for (Map.Entry<String, Object> entry : metadataMap.entrySet()) {
				jobDataMap.put(entry.getKey(), entry.getValue());
			}
			CronTrigger trigger = TriggerBuilder.newTrigger().withIdentity(job.getJobName(), job.getGroupName())
					.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpressStr())).build();

			scheduler.scheduleJob(jobDetail, trigger);
			// 启动scheduler
			startJobs();
		} catch (Exception e) {
			logger.error("Quartz定时任务添加定时任务失败...", e);
		}
	}

	/**
	 * 更新定时job
	 * 
	 * @param job
	 */
	public static void modifyJobCron(BaseQuartzJob job) {
		try {
			String triggerName = job.getJobName();
			String triggerGroupName = job.getGroupName();
			TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
			CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
			if (trigger == null) {
				return;
			}

			String oldCron = trigger.getCronExpression();
			if (!oldCron.equalsIgnoreCase(job.getCronExpressStr())) {
				// 修改时间
				trigger = trigger.getTriggerBuilder().withIdentity(triggerKey)
						.withSchedule(CronScheduleBuilder.cronSchedule(job.getCronExpressStr())).build();
				// 重启触发器
				scheduler.rescheduleJob(triggerKey, trigger);
			}
		} catch (Exception e) {
			logger.error("更新Quartz定时任务失败...", e);
		}
	}

	/**
	 * 暂停定时任务
	 * 
	 * @param job
	 */
	public static void pauseJob(BaseQuartzJob job) {
		handleJobStatus(1, job.getJobName(), job.getGroupName());
	}

	/**
	 * 删除定时任务
	 * 
	 * @param job
	 */
	public static void removeJob(BaseQuartzJob job) {
		handleJobStatus(3, job.getJobName(), job.getGroupName());
	}

	/**
	 * 恢复定时任务
	 * 
	 * @param job
	 */
	public static void recoverJob(BaseQuartzJob job) {
		handleJobStatus(2, job.getJobName(), job.getGroupName());
	}

	/**
	 * 更新定时任务状态
	 * 
	 * @param handleType
	 * @param jobName
	 * @param jobGroupName
	 */
	private static void handleJobStatus(int handleType, String jobName, String jobGroupName) {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroupName);
		try {
			switch (handleType) {
			case 1:
				scheduler.pauseJob(jobKey);
				break;
			case 2:
				scheduler.resumeJob(jobKey);
				break;
			case 3:
				scheduler.deleteJob(jobKey);
				break;
			default:
				break;
			}
		} catch (Exception e) {
			logger.error("处理Quartz定时任务状态失败...", e);
		}
	}
	
	/**
	 * 删除schduler中的job
	 * @param jobKeys
	 */
	public static void deleteJobList(List<JobKey> jobKeys) {
		try {
			scheduler.deleteJobs(jobKeys);
		} catch (Exception e) {
			logger.error("删除Quartz定时任务List失败...", e);
		}
	}
}
